from flask import Flask, render_template, request, redirect, flash, jsonify
from utils import read_hostapd_config, update_hostapd_config, get_connected_clients
import subprocess
import requests
import json
import re

app = Flask(__name__)
app.secret_key = "hotspot_secret"
@app.route("/")
def begin():
    return redirect("/login")

@app.route("/submit", methods=["POST"])
def submit_instruction():
    instruction = request.form["instruction"]

    # 构造 Prompt，强制引导只返回 JSON
    prompt = f"""
你是一个智能助手，请从用户输入中提取 WiFi 的 SSID 和密码，直接以 JSON 格式输出。
如果没有提供，则字段留空字符串。

【重要】：请严格输出以下格式：
{{"SSID": "xxx", "Password": "xxx"}}
禁止添加“输出：”、“解释：”、“如下”或 Markdown 代码块符号。
不要添加任何额外文字、空格或标点。

用户输入：{instruction}
"""

    try:
        # 请求本地模型接口，记得加 n_predict 参数
        response = requests.post(
            "http://127.0.0.1:8000/completion",
            json={
                "prompt": prompt,
                "stream": False,
                "temperature": 0.0,
                "n_predict": 128
            }
        )

        data = response.json()
        raw_output = data.get("response") or data.get("content") or data.get("text") or response.text
        print("模型原始输出：", raw_output)

        # 去除 markdown 包裹与输出前缀
        cleaned_output = re.sub(r"```json|```", "", raw_output).strip()
        cleaned_output = re.sub(r"输出：|解释：.*", "", cleaned_output).strip()

        # 提取所有 JSON 块，尝试逐个解析
        json_blocks = re.findall(r"\{.*?\}", cleaned_output, re.DOTALL)
        config_data = None
        for block in json_blocks:
            try:
                # 如果是转义的 JSON 字符串，先反转义
                if r'\"' in block:
                    block = bytes(block, "utf-8").decode("unicode_escape")
                config_data = json.loads(block)
                break
            except json.JSONDecodeError:
                continue

        if not config_data:
            raise ValueError("未能从模型输出中提取有效 JSON")

        # 提取字段
        ssid = config_data.get("SSID") or config_data.get("ssid") or ""
        password = config_data.get("Password") or config_data.get("password") or ""

        if not ssid and not password:
            flash(f"模型未能识别到有效的 SSID 或密码。<br><strong>原始输出：</strong><pre>{raw_output}</pre>", "warning")
            return redirect("/llm")

        # 读取现有配置文件
        with open("/etc/hostapd/hostapd.conf", "r") as f:
            lines = f.readlines()

        # 修改 ssid 和密码
        new_lines = []
        for line in lines:
            if line.startswith("ssid=") and ssid:
                new_lines.append(f"ssid={ssid}\n")
            elif line.startswith("wpa_passphrase=") and password:
                new_lines.append(f"wpa_passphrase={password}\n")
            else:
                new_lines.append(line)

        # 写入临时文件并覆盖原文件
        with open("/tmp/tmp_hostapd.conf", "w") as f:
            f.writelines(new_lines)

        subprocess.run(["sudo", "cp", "/etc/hostapd/hostapd.conf", "/etc/hostapd/hostapd.conf.bak"])
        subprocess.run(["sudo", "cp", "/tmp/tmp_hostapd.conf", "/etc/hostapd/hostapd.conf"])
        subprocess.run(["sudo", "rm", "/tmp/tmp_hostapd.conf"])
        subprocess.run(["sudo", "systemctl", "restart", "hostapd"])

        flash(f"配置成功：SSID={ssid}，密码={password}", "success")

    except Exception as e:
        flash(f"处理失败：{e}<br><strong>模型原始输出：</strong><pre>{raw_output}</pre>", "danger")

    return redirect("/llm")


@app.route("/index")
def index():
    config = read_hostapd_config()
    return render_template("index.html", config=config)

@app.route("/llm")
def llm_page():
    return render_template("llm.html")

@app.route("/update", methods=["POST"])
def update():
    ssid = request.form["ssid"]
    password = request.form["password"]
    channel = request.form["channel"]
    updates = {
        "ssid": ssid,
        "wpa_passphrase": password,
        "channel": channel
    }
    update_hostapd_config(updates)
    subprocess.run(["sudo", "systemctl", "restart", "hostapd"])
    flash("热点配置已更新，服务已重启。", "success")
    return redirect("/")

@app.route("/devices")
def devices():
    clients = get_connected_clients()
    return render_template("devices.html", clients=clients)

@app.route("/login", methods=["GET"])
def login():
    # 简单欢迎页面，不做任何拦截或认证
    client_ip = request.remote_addr
    return render_template("login.html", ip=client_ip)

@app.route("/info")
def hotspot_info():
    info = get_hotspot_info()
    return render_template("info.html", info=info)

@app.route("/devices/json")
def devices_json():
    clients = get_connected_clients()
    return jsonify(clients)

def get_hotspot_info():
    info = {}
    try:
        ip_output = subprocess.check_output(["ip", "addr", "show", "wlan0"]).decode()
        info["ip_info"] = ip_output
    except Exception as e:
        info["ip_info"] = f"无法获取 IP 信息: {e}"

    try:
        route_output = subprocess.check_output(["ip", "route"]).decode()
        info["route_info"] = route_output
    except Exception as e:
        info["route_info"] = f"无法获取路由信息: {e}"

    try:
        with open("/etc/resolv.conf", "r") as f:
            info["dns_info"] = f.read()
    except Exception as e:
        info["dns_info"] = f"无法读取 DNS 信息: {e}"

    return info

if __name__ == "__main__":
    app.run(host="0.0.0.0", port=8080)
